package apply.apply2;

import apply.data.Person;
import org.junit.Test;

import java.lang.reflect.*;

/**
 * 反射应用2：获取运行时类的内部结构
 * - 获取运行时类的内部结构1：所有属性、所有方法、所有构造器
 * - 获取运行时类的内部结构2：父类、接口、包、带泛型的父类、父类的泛型等。
 */
public class ApplyTest {
    @Test
    public void test1() {
        Class<Person> clazz = Person.class;

        System.out.println("----获取属性 getFields()-----");
        // getFields()：获取当前类本身及其所有的父类中声明为public权限的属性。
        Field[] fields = clazz.getFields();
        for (Field f : fields) {
            System.out.println(f);
        }

        System.out.println("----获取属性 getDeclaredFields()-----");
        // getDeclaredFields():获取当前运行时类中声明的所有的属性
        // 不包含继承的属性
        Field[] declaredFields = clazz.getDeclaredFields();
        for (Field f : declaredFields) {
            /*
             * 0x是十六进制
             * PUBLIC    0x00000001;  1      1
             * PRIVATE   0x00000002;  2     10
             * PROTECTED 0x00000004;  4    100
             * STATIC    0x00000008;  8   1000
             * FINAL     0x00000010;  16 10000
             * ...
             */

            // 1.权限修饰符
            int modifiers = f.getModifiers();
            System.out.print(modifiers + ":\t" + Modifier.toString(modifiers) + "\t");

            // 2.数据类型
            Class<?> type = f.getType();
            System.out.print(type.getName() + "\t");

            // 3. 变量名
            String fName = f.getName();
            System.out.print(fName);
            System.out.println();
        }

        System.out.println("----获取方法 getMethods()-----");
        Method[] methods = clazz.getMethods();
        for (Method me : methods) {
            System.out.println(me);
        }
        System.out.println("----获取方法 getDeclaredMethods()-----");
        Method[] declaredMethods = clazz.getDeclaredMethods();
        for (Method m : declaredMethods) {
            System.out.println(m);
        }
    }

    @Test
    public void test2() throws ClassNotFoundException {

        Class<?> aClass = Class.forName("apply.data.Person");

        // class apply.data.Creature 获取父类
        Class<?> superclass = aClass.getSuperclass();
        System.out.println(superclass);

        // apply.data.Creature<java.lang.String>  获取带泛型父类
        Type genericSuperclass = aClass.getGenericSuperclass();
        System.out.println(genericSuperclass);

        /*
            获取接口
            interface java.lang.Comparable
            interface apply.data.MyInterface
         */
        Class<?>[] interfaces = aClass.getInterfaces();
        for (Class<?> i : interfaces) {
            System.out.println(i);
        }

        // 获取运行时类所在的包  package apply.data
        Package aPackage = aClass.getPackage();
        System.out.println(aPackage);

        // 获取运行时类的父类的泛型

        // genericSuperclass--> Type 是一个接口，Class实现了此接口

        // 如果父类是带泛型的，则可以强转为 parameterizedType
        ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass;
        System.out.println(parameterizedType);

        // 调用 getActualTypeArguments() 方法获取泛型的参数，结果是一个数组，因为可能有多个泛型参数。
        Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();

        for (Type t : actualTypeArguments) {
            System.out.println(t);                          // class java.lang.String
            // 获取泛型参数的名称
            System.out.println(((Class<?>) t).getName());   // java.lang.String
        }

    }
}
